package org.giorgiocalderolla.showrssx;

import java.util.Observable;
import java.util.Observer;
import java.util.Timer;

import org.giorgiocalderolla.showrssx.Configuration.Status;

/**
 * @author Giorgio Calderolla
 * 
 *         The application class, initialises every needed component
 */
public class ShowRSSX implements Observer {

	// global application-related constants
	public static final String APPLICATION_NAME = "ShowRSSX";
	public static final String APPLICATION_VERSION = "1.2";
	public static final String APPLICATION_WEBSITE_URL = "http://code.google.com/p/showrssx/";
	public static final String APPLICATION_BUG_REPORT_URL = APPLICATION_WEBSITE_URL
			+ "issues/entry?template=Defect%20report%20from%20user";
	public static final String APPLICATION_FEATURE_REQUEST_URL = APPLICATION_WEBSITE_URL
			+ "issues/entry?template=Feature%20request";
	public static final String APPLICATION_CONFIGURATION_URL = APPLICATION_WEBSITE_URL
			+ "wiki/Configuration";
	public static final String SERVICE_WEBSITE_URL = "http://showrss.karmorra.info/";

	// components
	private FeedChecker rssCheck = null;
	private Timer rssCheckTimer = null;
	private GUI gui = null;
	private Configuration configuration = null;

	/**
	 * Constructor, loads the configuration manager, builds the UI and starts
	 * the required threads
	 */
	private ShowRSSX() {

		// load the configuration manager
		configuration = new Configuration();

		// build the UI
		gui = new GUI(this, configuration);

		// let the GUI and us observe configuration changes
		configuration.addObserver(this);
		configuration.addObserver(gui);

		// prompt the user for configuration if the application isn't already
		// configured
		if (!configuration.isConfigured()) {
			gui.showPreferences();
		} else {
			// initialise and start the feed checkers
			configuration.setCurrentStatus(Status.ACTIVE_IDLE);

			resume();
		}
	}

	/**
	 * This is called whenever an observed object changes. We are only
	 * interested in Configuration changes
	 */
	@Override
	public void update(Observable observable, Object changedPreference) {

		// has the configuration changed? is it in a valid state?
		if ((observable == configuration) && configuration.isConfigured()) {
			// if the update interval has changed, reschedule the rss checker
			// also if the application is properly configured
			if ((changedPreference == Configuration.PREFERENCE_UPDATE_INTERVAL)
					|| (changedPreference == Configuration.PREFERENCE_CONFIGURED)) {
				// stop, destroy and recreate our scheduled task
				// but only if the app isn't paused!
				if (configuration.getCurrentStatus() != Status.DISABLED) {
					pause();
					resume();
				}
			}
		}
	}

	/**
	 * Cancels running tasks
	 */
	public synchronized void pause() {

		if (configuration.isConfigured()) {
			if (rssCheckTimer != null) {
				rssCheckTimer.cancel();
			}
		}

		configuration.setCurrentStatus(Status.DISABLED);
	}

	/**
	 * Resumes feed checking
	 */
	public synchronized void resume() {

		configuration.setCurrentStatus(Status.ACTIVE_IDLE);

		if (configuration.isConfigured()) {
			rssCheck = new FeedChecker(configuration);
			rssCheckTimer = new Timer(true);
			rssCheckTimer.scheduleAtFixedRate(rssCheck, 0, configuration
					.getUpdateInterval() * 60 * 1000);
		}
	}

	/**
	 * Cancels running tasks and quits
	 */
	public void quit() {

		pause();

		abort();
	}

	/**
	 * Exits the application
	 */
	public static void abort() {
		System.exit(-1);
	}

	/**
	 * Runs the application
	 * 
	 * @param args
	 *            command-line arguments, ignored
	 */
	public static void main(String[] args) {
		new ShowRSSX();
	}
}
